// RAP [rh] DnD not supported
///*******************************************************************************
// * Copyright (c) 2004, 2008 IBM Corporation and others.
// * All rights reserved. This program and the accompanying materials
// * are made available under the terms of the Eclipse Public License v1.0
// * which accompanies this distribution, and is available at
// * http://www.eclipse.org/legal/epl-v10.html
// *
// * Contributors:
// *     IBM Corporation - initial API and implementation
// *******************************************************************************/
//package org.eclipse.ui.internal;
//
//import java.util.Iterator;
//import java.util.List;
//
//import org.eclipse.jface.util.Geometry;
//import org.eclipse.swt.SWT;
//import org.eclipse.swt.graphics.Cursor;
//import org.eclipse.swt.graphics.Point;
//import org.eclipse.swt.graphics.Rectangle;
//import org.eclipse.swt.widgets.Composite;
//import org.eclipse.swt.widgets.Control;
//import org.eclipse.ui.internal.dnd.DragBorder;
//import org.eclipse.ui.internal.dnd.DragUtil;
//import org.eclipse.ui.internal.dnd.IDragOverListener;
//import org.eclipse.ui.internal.dnd.IDropTarget;
//import org.eclipse.ui.internal.dnd.IDropTarget2;
//import org.eclipse.ui.internal.layout.IWindowTrim;
//import org.eclipse.ui.internal.layout.LayoutUtil;
//import org.eclipse.ui.internal.layout.TrimDescriptor;
//import org.eclipse.ui.internal.layout.TrimLayout;
//import org.eclipse.ui.internal.layout.TrimToolBarBase;
//
///**
// */
///*package*/class TrimDropTarget implements IDragOverListener {
//	
//    private final class ActualTrimDropTarget implements IDropTarget2 {
//        public IWindowTrim draggedTrim;
//        
//        // tracking parameters
//    	private DragBorder border = null;
//    	private int dockedArea;
//        
//        // Holder for the position of trim that is 'floating' with the cursor
//    	private int cursorAreaId;
//        private int initialAreaId;
//        private IWindowTrim initialInsertBefore;        
//		private Rectangle initialLocation;
//
//        /**
//         * Constructor
//         */
//        private ActualTrimDropTarget() {
//            super();
//
//            draggedTrim = null;
//            dockedArea = SWT.NONE;
//            
//            initialAreaId = SWT.NONE;
//            initialInsertBefore = null;
//        }
//        
//        /**
//         * This method is used to delineate separate trims dragging events. The -first- drag
//         * event will set this and then it will remain constant until the drag gesture is done;
//         * either by dropping or escaping. Once the gesture is finished the trim value is set
//         * back to 'null'.
//         * 
//         * @param trim The trim item currently being dragged.
//         */
//        public void startDrag(IWindowTrim trim) {
//        	// Are we starting a new drag?
//        	if (draggedTrim != trim) {
//            	// remember the dragged trim
//            	draggedTrim = trim;
//            	
//            	// Remember the location that we were in initially so we
//            	// can go back there on an cancel...
//            	initialAreaId = layout.getTrimAreaId(draggedTrim.getControl());
//            	
//            	// Determine who we were placed 'before' in the trim
//            	initialInsertBefore = getInsertBefore(initialAreaId, draggedTrim);
//            	
//            	// Remember the location that the control used to be at for animation purposes
//            	initialLocation = DragUtil.getDisplayBounds(draggedTrim.getControl());
//            	            	
//            	// The dragged trim is always initially docked
//            	dockedArea = initialAreaId;
//        	}
//        }
//                
//        /**
//         * Determine the trim area from the point. To avoid clashing at the 'corners' due to extending the trim area's
//         * rectangles we first ensure that the point is not actually -within- a trim area before we check the extended
//         * rectangles.
//         * 
//         * @param pos The current cursor pos
//         * @return the Trim area that the cursor is in or SWT.NONE if the point is not in an area
//         */
//        private int getTrimArea(Point pos) {
//        	// First, check if we're actually -within- a trim area (i.e. no boundary extensions)
//        	int areaId = getTrimArea(pos, 0);
//        	
//        	// If we are not inside a trim area...are we 'close' to one?
//        	if (areaId == SWT.NONE) {
//				areaId = getTrimArea(pos, TrimDragPreferences.getThreshold());
//			}
//        	
//        	// not inside any trim area
//        	return areaId;
//        }
//        
//        /**
//         * Checks the trims areas against the given position. Each trim area is 'extended' into
//         * the workbench page by the value of <code>extendedBoundaryWidth</code> before the checking
//         * takes place.
//         * 
//         * @param pos The point to check against
//         * @param extendedBoundaryWidth The amount to extend the trim area's 'inner' edge by
//         * 
//         * @return The trim area or SWT.NONE if the point is not within any extended trim area's rect.
//         */
//        private int getTrimArea(Point pos, int extendedBoundaryWidth) {
//        	int[] areaIds = layout.getAreaIds();
//        	for (int i = 0; i < areaIds.length; i++) {
//				Rectangle trimRect = layout.getTrimRect(windowComposite, areaIds[i]);
//				trimRect = Geometry.toControl(windowComposite, trimRect);
//
//				// Only check 'valid' sides
//				if ( (areaIds[i] & getValidSides()) != SWT.NONE) {
//					// TODO: more confusion binding 'areaIds' to SWT 'sides'
//		        	switch (areaIds[i]) {
//					case SWT.LEFT:
//						trimRect.width += extendedBoundaryWidth;
//						
//						if (pos.y >= trimRect.y &&
//							pos.y <= (trimRect.y+trimRect.height) &&
//							pos.x <= (trimRect.x+trimRect.width)) {
//							return areaIds[i];
//						}
//						break;
//					case SWT.RIGHT:
//						trimRect.x -= extendedBoundaryWidth;
//						trimRect.width += extendedBoundaryWidth;
//						
//						if (pos.y >= trimRect.y &&
//							pos.y <= (trimRect.y+trimRect.height) &&
//							pos.x >= trimRect.x) {
//							return areaIds[i];
//						}
//						break;
//					case SWT.TOP:
//						trimRect.height += extendedBoundaryWidth;
//						
//						if (pos.x >= trimRect.x &&
//							pos.x <= (trimRect.x+trimRect.width) &&
//							pos.y <= (trimRect.y+trimRect.height)) {
//							return areaIds[i];
//						}
//						break;
//					case SWT.BOTTOM:
//						trimRect.y -= extendedBoundaryWidth;
//						trimRect.height += extendedBoundaryWidth;
//						
//						if (pos.x >= trimRect.x &&
//							pos.x <= (trimRect.x+trimRect.width) &&
//							pos.y >= trimRect.y) {
//							return areaIds[i];
//						}
//						break;
//		        	}
//				}
//			}
//        	
//        	// not inside any trim area
//        	return SWT.NONE;
//        }
//        
//        /**
//         * Determine the window trim that the currently dragged trim should be inserted
//         * before.
//         * @param areaId The area id that is being checked
//         * @param pos The position used to determine the correct insertion trim
//         * @return The trim to 'dock' the draggedTrim before
//         */
//        private IWindowTrim getInsertBefore(int areaId, Point pos) {
//        	boolean isHorizontal = (areaId == SWT.TOP) || (areaId == SWT.BOTTOM);
//        	
//        	// Walk the trim area and return the first one that the positon
//        	// is 'after'.
//        	List tDescs = layout.getTrimArea(areaId).getDescriptors();
//        	for (Iterator iter = tDescs.iterator(); iter.hasNext();) {
//				TrimDescriptor desc = (TrimDescriptor) iter.next();
//				
//				// Skip ourselves
//				if (desc.getTrim() == draggedTrim) {
//					continue;
//				}
//				
//				// Now, check
//				Rectangle bb = desc.getCache().getControl().getBounds();
//				Point center = Geometry.centerPoint(bb);
//				if (isHorizontal) {
//					if (pos.x < center.x) {
//						return desc.getTrim();
//					}
//				}
//				else {
//					if (pos.y < center.y) {
//						return desc.getTrim();
//					}
//				}
//			}
//        	
//        	return null;
//        }
//        
//        /**
//         * Returns the trim that is 'before' the given trim in the given area
//         * 
//         * @param areaId The areaId of the trim
//         * @param trim The trim to find the element after
//         * 
//         * @return The trim that the given trim is 'before'
//         */
//        private IWindowTrim getInsertBefore(int areaId, IWindowTrim trim) {
//        	List tDescs = layout.getTrimArea(areaId).getDescriptors();
//        	for (Iterator iter = tDescs.iterator(); iter.hasNext();) {
//				TrimDescriptor desc = (TrimDescriptor) iter.next();
//				if (desc.getTrim() == trim) {
//					if (iter.hasNext()) {
//						desc = (TrimDescriptor) iter.next();
//						return desc.getTrim();
//					}
//					return null;
//				}
//			}
//        	
//        	return null;
//        }
//        
//        /**
//         * Recalculates the drop information based on the current cursor pos.
//         * 
//         * @param pos The cursor position
//         */
//        public void track(Point pos) {
//        	// Convert the mouse positon into 'local' coords
//        	Rectangle r = new Rectangle(pos.x, pos.y, 1,1);
//        	r = Geometry.toControl(windowComposite, r);
//        	pos.x = r.x;
//        	pos.y = r.y;
//        	        	
//        	// Are we 'inside' a trim area ?
//        	cursorAreaId = getTrimArea(pos);
//
//        	// Provide tracking for the appropriate 'mode'
//        	if (cursorAreaId != SWT.NONE) {
//				trackInsideTrimArea(pos);
//			} else {
//				trackOutsideTrimArea(pos);
//			}
//        }
//       
//        /**
//         * Perform the feedback used when the cursor is 'inside' a particular trim area.
//         * The current implementation will place the dragged trim into the trim area at
//         * the location determined by the supplied point.
//         * 
//         * @param pos The point to use to determine where in the trim area the dragged trim
//         * should be located.
//         */
//        private void trackInsideTrimArea(Point pos) {
//        	// Where should we be?
//        	int newArea = getTrimArea(pos);
//        	IWindowTrim newInsertBefore = getInsertBefore(newArea, pos);
//
//        	// if we're currently undocked then we should dock
//        	boolean shouldDock = dockedArea == SWT.NONE;
//        	
//        	// If we're already docked then only update if there's a change in area or position
//        	if (dockedArea != SWT.NONE) {
//	        	// Where are we now?
//	        	IWindowTrim curInsertBefore = getInsertBefore(dockedArea, draggedTrim);
//	        	
//	        	// If we're already docked we should only update if there's a change
//	        	shouldDock = dockedArea != newArea || curInsertBefore != newInsertBefore;
//        	}
//        	
//        	// Do we have to do anything?
//        	if (shouldDock) {
//        		// (Re)dock the trim in the new location
//        		dock(newArea, newInsertBefore);
//        	}
//        }
//        
//        /**
//         * Provide the dragging feedback when the cursor is -not- explicitly inside
//         * a particular trim area.
//         * 
//         */
//        private void trackOutsideTrimArea(Point pos) {
//        	// If we -were- docked then undock
//        	if (dockedArea != SWT.NONE) {
//				undock();
//			}
//    		
//    		border.setLocation(pos, SWT.BOTTOM);
//        }
//                
//        /**
//         * Return the set of valid sides that a piece of trim can be docked on. We
//         * arbitrarily extend this to include any areas that won't cause a change in orientation
//         * 
//         * @return The extended drop 'side' set
//         */
//        private int getValidSides() {
//        	int result = draggedTrim.getValidSides();
//        	if (result == SWT.NONE) {
//				return result;
//			}
//
//        	// For now, if we can dock...we can dock -anywhere-
//        	return SWT.TOP | SWT.BOTTOM | SWT.LEFT | SWT.RIGHT;
//        }
//
//        /**
//         * The user either cancelled the drag or tried to drop the trim in an invalid
//         * area...put the trim back in the last location it was in
//         */
//        private void redock() {
//    		// animate the 'redock'
//        	Rectangle startRect = DragUtil.getDisplayBounds(draggedTrim.getControl());
//    		AnimationEngine.createTweakedAnimation(windowComposite.getShell(), 400, startRect, initialLocation);
//
//            dock(initialAreaId, initialInsertBefore);
//        }
//        
//		/* (non-Javadoc)
//         * @see org.eclipse.ui.internal.dnd.IDropTarget#drop()
//         */
//        public void drop() {
//        	// If we aren't docked then restore the initial location
//        	if (dockedArea == SWT.NONE) {
//				redock();
//			}
//        }
//
//        /**
//         * Remove the trim frmo its current 'docked' location and attach it
//         * to the cursor...
//         */
//        private void undock() {
//        	// Remove the trim from the layout
//        	layout.removeTrim(draggedTrim);
//           	LayoutUtil.resize(draggedTrim.getControl());
//           	
//           	// Re-orient the widget to its -original- side and size
//        	draggedTrim.dock(initialAreaId);
//        	draggedTrim.getControl().setSize(initialLocation.width, initialLocation.height);
//           	
//           	// Create a new dragging border onto the dragged trim
//        	// Special check for TrimPart...should be generalized
//        	boolean wantsFrame = !(draggedTrim instanceof TrimToolBarBase);
//           	border = new DragBorder(windowComposite, draggedTrim.getControl(), wantsFrame);
//
//           	dockedArea = SWT.NONE;
//        }
//        
//        /**
//         * Return the 'undocked' trim to its previous location in the layout
//         */
//        private void dock(int areaId, IWindowTrim insertBefore) {
//        	// remove the drag 'border'
//        	if (border != null) {
//				border.dispose();
//				border = null;
//        	}
//			
//			// Update the trim's orientation if necessary
//			draggedTrim.dock(areaId);
//
//			// Add the trim into the layout
//            layout.addTrim(areaId, draggedTrim, insertBefore);
//           	LayoutUtil.resize(draggedTrim.getControl());
//           	
//           	// Remember the area that we're currently docked in
//           	dockedArea = areaId;
//        }
//        	
//        /* (non-Javadoc)
//         * @see org.eclipse.ui.internal.dnd.IDropTarget#getCursor()
//         */
//        public Cursor getCursor() {
//        	// If the trim isn't docked then show the 'no smoking' sign
//        	if (cursorAreaId == SWT.NONE) {
//				return windowComposite.getDisplay().getSystemCursor(SWT.CURSOR_NO);
//			}
//        	
//        	// It's docked; show the four-way arrow cursor
//        	return windowComposite.getDisplay().getSystemCursor(SWT.CURSOR_SIZEALL);
//        }
//
//        /* (non-Javadoc)
//         * @see org.eclipse.ui.internal.dnd.IDropTarget#getSnapRectangle()
//         */
//        public Rectangle getSnapRectangle() {
//        	// TODO: KLUDGE!! We don't want to show -any- snap rect
//        	// but Tracker won't allow that so place it where it won't be visible
//        	return new Rectangle(100000, 0,0,0);
//        }
//
//		/* (non-Javadoc)
//		 * @see org.eclipse.ui.internal.dnd.IDropTarget2#dragFinished(boolean)
//		 */
//		public void dragFinished(boolean dropPerformed) {
//			// If we didn't perform a drop then restore the original position
//			if (!dropPerformed && dockedArea == SWT.NONE) {
//				// Force the dragged trim back into its original position...				
//				redock();
//			}
//			
//			// Set the draggedTrim to null. This indicates that we're no longer
//			// dragging the trim. The first call to the TrimDropTarget's 'drag' method
//			// will reset this the next time a drag starts.
//			draggedTrim = null;
//		}
//    }
//    
//    private ActualTrimDropTarget dropTarget;
//    
//    private TrimLayout layout;
//    private Composite windowComposite;
//
//    /**
//     * Create a new drop target capable of accepting IWindowTrim items
//     * 
//     * @param someComposite The control owning the TrimLayout
//     * @param theWindow the workbenchWindow
//     */
//    public TrimDropTarget(Composite someComposite, WorkbenchWindow theWindow) {
//        layout = (TrimLayout) someComposite.getLayout();
//        windowComposite = someComposite;
//
//        // Create an instance of a drop target to use
//        dropTarget = new ActualTrimDropTarget();
//    }
//
//    /* (non-Javadoc)
//     * @see org.eclipse.ui.internal.dnd.IDragOverListener#drag(org.eclipse.swt.widgets.Control, java.lang.Object, org.eclipse.swt.graphics.Point, org.eclipse.swt.graphics.Rectangle)
//     */
//    public IDropTarget drag(Control currentControl, Object draggedObject,
//            Point position, final Rectangle dragRectangle) {
//    	
//    	// Have to be dragging trim
//    	if (!(draggedObject instanceof IWindowTrim)) {
//			return null;
//		}
//    	
//    	// OK, we're dragging trim. is it from -this- shell?
//    	IWindowTrim trim = (IWindowTrim) draggedObject;
//    	if (trim.getControl().getShell() != windowComposite.getShell()) {
//			return null;
//		}
//    	
//    	// If this is the -first- drag then inform the drop target
//    	if (dropTarget.draggedTrim == null) {
//    		dropTarget.startDrag(trim);
//    	}
//
//    	// Forward on to the 'actual' drop target for feedback
//    	dropTarget.track(position);
//    	
//    	// Spin the paint loop after every track
//    	windowComposite.getDisplay().update();
//    	
//		return dropTarget;
//    }
//}
